package com.example.xiaomi;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.util.LinkedList;
import java.util.Stack;

public class MainActivity extends Activity implements View.OnClickListener {
    Button btn_1;
    Button btn_0;
    Button btn_2;
    Button btn_7;
    Button btn_3;
    Button btn_8;
    Button btn_plus;
    Button btn_4;
    Button btn_9;
    Button btn_minus;
    Button btn_5;
    Button btn_a;
    Button btn_multipy;
    Button btn_divide;
    Button btn_del;
    Button btn_6;
    Button btn_b;
    Button btn_clear;
    EditText et_input;
    boolean clear_flag;
    Stack<String> operator = new Stack<>();
    //    Stack<Double> result = new Stack<>();
    LinkedList<String> operand = new LinkedList<>();

    //clearflag默认为false
    // 定义这些按钮和文本框
    //通过接口方式实现事件的监听
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_0 = (Button) findViewById(R.id.btn_0);
        btn_1 = (Button) findViewById(R.id.btn_1);
        btn_2 = (Button) findViewById(R.id.btn_2);
        btn_3 = (Button) findViewById(R.id.btn_3);
        btn_4 = (Button) findViewById(R.id.btn_4);
        btn_9 = (Button) findViewById(R.id.btn_9);
        btn_5 = (Button) findViewById(R.id.btn_5);
        btn_6 = (Button) findViewById(R.id.btn_6);
        btn_7 = (Button) findViewById(R.id.btn_7);
        btn_8 = (Button) findViewById(R.id.btn_8);
        btn_clear = (Button) findViewById(R.id.btn_clear);
        btn_del = (Button) findViewById(R.id.btn_del);
        btn_divide = (Button) findViewById(R.id.btn_divide);
        btn_multipy = (Button) findViewById(R.id.btn_multipy);
        btn_minus = (Button) findViewById(R.id.btn_minus);
        btn_plus = (Button) findViewById(R.id.btn_plus);
        btn_a = (Button) findViewById(R.id.btn_a);
        btn_b = (Button) findViewById(R.id.btn_b);
        //实例化按钮
        // 返回的是view类型，需要转换成button类型
        et_input = (EditText) findViewById(R.id.et_input);
        btn_0.setOnClickListener(this);
        btn_1.setOnClickListener(this);
        btn_2.setOnClickListener(this);
        btn_3.setOnClickListener(this);
        btn_4.setOnClickListener(this);
        btn_5.setOnClickListener(this);
        btn_6.setOnClickListener(this);
        btn_7.setOnClickListener(this);
        btn_8.setOnClickListener(this);
        btn_9.setOnClickListener(this);
        btn_a.setOnClickListener(this);
        btn_b.setOnClickListener(this);
        btn_del.setOnClickListener(this);
        btn_minus.setOnClickListener(this);
        btn_multipy.setOnClickListener(this);
        btn_divide.setOnClickListener(this);
        btn_plus.setOnClickListener(this);
        btn_clear.setOnClickListener(this);
        //设置按钮的点击事件
        //大概是获取点击事件
    }

    @Override
    public void onClick(View v) {
        String str = et_input.getText().toString();
//        System.err.println(str + "------------------------------");
        switch (v.getId()) {
            case R.id.btn_0:
            case R.id.btn_1:
            case R.id.btn_2:
            case R.id.btn_3:
            case R.id.btn_4:
            case R.id.btn_5:
            case R.id.btn_6:
            case R.id.btn_7:
            case R.id.btn_8:
            case R.id.btn_9:
            case R.id.btn_b:
                if (clear_flag) {
                    clear_flag = false;
                    str = "";
                    et_input.setText("");
                }
                et_input.setText(str + ((Button) v).getText());
                break;
            case R.id.btn_plus:
            case R.id.btn_multipy:
            case R.id.btn_divide:
            case R.id.btn_minus:
                if (clear_flag) {
                    clear_flag = false;
                    str = "";
                    et_input.setText("");
                }
                //判断用
                et_input.setText(str + " " + ((Button) v).getText() + " ");
                break;
            case R.id.btn_clear:
                if (clear_flag) {
                    clear_flag = false;
                    str = "";
                    et_input.setText("");
                }
                et_input.setText("");
                break;
            case R.id.btn_del:
                if (clear_flag) {
                    clear_flag = false;
                    str = "";
                    et_input.setText("");
                }
                if (str != null && !str.equals("")) {
                    et_input.setText(str.substring(0, str.length() - 1));
                }
                break;
            case R.id.btn_a:
                getresult();
                break;
        }
    }

    private void getresult() {
        String exp = et_input.getText().toString();
        System.err.println(exp + "--------------结果字符串----------------");

        if (exp == null || exp.equals("")) {
            return;
        }
        if (!exp.contains(" ")) {
            return;
        }
        if (clear_flag) {
            clear_flag = false;
            return;
        }
        clear_flag = true;
//

//      中缀表达式转后缀表达式
        /**
         * 设定一个栈SOP,和一个线性表 L 。SOP用于临时存储运算符和左括号分界符( ，L用于存储后缀表达式。
         * 遍历原始表达式中的每一个表达式元素
         * （1）如果是操作数，则直接追加到 L中。只有 运算符 或者 分界符（ 才可以存放到 栈SOP中
         * （2）如果是运算符（用op1表示）
         *         Ⅰ如果SOP栈顶元素（用op2表示） 不是运算符，则二者没有可比性，则直接将此运算符op1压栈。 例如栈顶是左括号 ( ，或者栈为空。
         *          Ⅱ 如果SOP栈顶元素（用op2表示） 是运算符 ，则比较op1和 op2的优先级。如果op1 > op2 ，则直接将此运算符op1压栈。
         * 如果不满足op1 > op2，则将op2出栈，并追加到L，重复步骤2。
         * 也就是说，如果在SOP栈中，有2个相邻的元素都是运算符，则他们必须满足：下层运算符的优先级一定小于上层元素的优先级，才能相邻。
         *
         * 最后，如果SOP中还有元素，则依次弹出追加到L后，就得到了后缀表达式。
         */
        String[] strarray = exp.split(" ");
        for (int i = 0; i < strarray.length; i++) {
            if (strarray[i].equals("＋") || strarray[i].equals("－") || strarray[i].equals("×") || strarray[i].equals("÷")) {
                while (!operator.empty() && ((strarray[i].equals("＋") || strarray[i].equals("－")) || ((strarray[i].equals("×") || strarray[i].equals("÷")) && (operator.peek().equals("×") || operator.peek().equals("÷"))))) {
                    operand.add(operator.pop());
                }
                operator.push(strarray[i]);
            } else operand.add(strarray[i]);
        }
        while (!operator.empty()) {
            operand.add(operator.pop());
        }
        System.out.println(operand + "后缀表达式");


//        遍历后缀表达式求值 遇操作数入栈  遇操作符号 先判断此时栈中操作数数量是否合法 然后从栈中弹出两个操作数进行计算 计算结果再次入栈
//        如此依次循环遍历后缀表达式完毕后 可得到最后结果 （记得除0异常）
        Stack<Double> number = new Stack<>();
        boolean flag_0 = false;//除零标志
        boolean flag_1 = true;//输入是否合法标志
        for (String str : operand) {
            double result = 0;
            if (!str.equals("＋") && !str.equals("－") && !str.equals("×") && !str.equals("÷")) {
                number.push(Double.parseDouble(str));
            } else {
                String op = str;
                if (number.size() < 2) {//操作数少于两个 不合法
                    flag_1 = false;
                } else {
                    double d1 = number.pop();
                    double d2 = number.pop();
                    if (op.equals("＋")) {
                        result = d1 + d2;
                    } else if (op.equals("－")) {
                        result = d2 - d1;
                    } else if (op.equals("×")) {
                        result = d1 * d2;
                    } else if (op.equals("÷")) {
                        if (d1 == 0) {
                            result = Double.MAX_VALUE;
                            flag_0 = true;
                        } else result = d2 / d1;
                    }
                    number.push(result);
                }
            }
        }
//        循环完毕后 记得清空列表
        operand.clear();
        Double result = number.pop();
        if (!flag_1) et_input.setText("请输入合法的运算表达式！");
        else if (flag_0) et_input.setText("除数不能为零！");
        else if (String.valueOf(result).endsWith("0")) {
            et_input.setText(result.intValue() + "");
        } else et_input.setText(result + "");

    }
}